package cn.iocoder.yudao.module.biobee.service.plot;

import cn.hutool.core.io.FileUtil;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.module.biobee.controller.admin.plot.vo.PlotSubmitTaskReqVO;
import cn.iocoder.yudao.module.biobee.controller.admin.plot.vo.PlotUploadFileReqVO;
import cn.iocoder.yudao.module.biobee.controller.admin.tasklist.vo.TaskListSaveReqVO;
import cn.iocoder.yudao.module.biobee.convert.plot.PlotConvert;
import cn.iocoder.yudao.module.biobee.dal.mysql.tasklist.TaskListMapper;
import cn.iocoder.yudao.module.biobee.service.tasklist.TaskListServiceImpl;
import cn.iocoder.yudao.module.biobee.utils.BioBeeUtils;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;

import static cn.iocoder.yudao.module.infra.framework.file.core.utils.FileTypeUtils.writeAttachment;


@Service("plotService")
public class PlotServiceImpl implements PlotService {

    @Value("${biobee.base-path}")
    private String basePath;
    @Value("${biobee.cli-path}")
    private String cliPath;

    @Value("${biobee.scripts-path}")
    private String scriptsPath;

    @Resource
    private TaskListServiceImpl taskListService;

    @Resource
    private TaskListMapper taskListMapper;


    @Override
    public void submitTask(@Valid PlotSubmitTaskReqVO plotSubmitTaskReqVO) throws IOException {
        try {
            Long tenantId = TenantContextHolder.getTenantId();
            String taskDirPath = BioBeeUtils.buildPath(
                    basePath,
                    "projects",
                    String.valueOf(tenantId),
                    plotSubmitTaskReqVO.getProjectId(),
                    plotSubmitTaskReqVO.getTaskId()
            );
            String inputDirPath = BioBeeUtils.buildPath(taskDirPath, "input");
            String outputDirPath = BioBeeUtils.buildPath(taskDirPath, "output");
            String logDirPath = BioBeeUtils.buildPath(taskDirPath, "log");
            String jsonFilePath = BioBeeUtils.buildPath(outputDirPath, "result.json");
            String shellFilePath = BioBeeUtils.buildPath(logDirPath, "work.sh");
            String logFilePath = BioBeeUtils.buildPath(logDirPath, "work.log");
            // 2. 创建目录（分别判断）
            BioBeeUtils.createDirIfNotExist(taskDirPath);
            BioBeeUtils.createDirIfNotExist(inputDirPath);
            BioBeeUtils.createDirIfNotExist(outputDirPath);
            BioBeeUtils.createDirIfNotExist(logDirPath);
            // 5. 将参数对象写入 JSON 文件
            ObjectMapper objectMapper = new ObjectMapper();
            objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
            objectMapper.writerWithDefaultPrettyPrinter().writeValue(new File(jsonFilePath), plotSubmitTaskReqVO);
            // 6. 构造执行命令（注意避免命令注入）
            List<String> cmdList = Arrays.asList(
                    "cd",
                    taskDirPath,
                    "&&",
                    cliPath,
                    plotSubmitTaskReqVO.getTaskType()
            );
            // 7. 执行 Shell 命令
            String command = String.join(" ", cmdList);
            BioBeeUtils.execute(command, shellFilePath, logFilePath);
            TaskListSaveReqVO taskListSaveReqVO = PlotConvert.INSTANCE.convert(plotSubmitTaskReqVO);
            taskListService.createOrUpdateByProjectId(taskListSaveReqVO);
        } catch (Exception e) {
            throw new IOException("任务提交失败：" + e.getMessage(), e);
        }
    }

    public void uploadFile(PlotUploadFileReqVO plotUploadFileReqVO) throws IOException {
        try {
            Long tenantId = TenantContextHolder.getTenantId();
            Path uploadDir = Paths.get(
                    basePath,
                    "projects",
                    tenantId.toString(),
                    String.valueOf(plotUploadFileReqVO.getProjectId()),
                    String.valueOf(plotUploadFileReqVO.getTaskId()),
                    "input"
            );
            BioBeeUtils.saveMultipartFile(plotUploadFileReqVO.getFile(), uploadDir);
        } catch (Exception err) {
            throw new IOException("文件上传失败：" + err.getMessage(), err);
        }
    }

    public void downloadResult(HttpServletResponse response, String projectId, String taskId, String fileName) throws IOException {
        try {
            Long tenantId = TenantContextHolder.getTenantId();
            String resultPath = BioBeeUtils.buildPath(
                    basePath,
                    "projects",
                    String.valueOf(tenantId),
                    projectId,
                    taskId,
                    "output",
                    fileName
            );
            writeAttachment(response, fileName, FileUtil.readBytes(resultPath));
        } catch (Exception err) {
            throw new IOException("文件下载失败：" + err.getMessage(), err);
        }
    }

    public void downloadExample(HttpServletResponse response, String projectType, String taskType, String fileName) throws IOException {
        try {
            String resultPath = BioBeeUtils.buildPath(
                    scriptsPath,
                    projectType,
                    taskType,
                    fileName
            );
            writeAttachment(response, fileName, FileUtil.readBytes(resultPath));
        } catch (Exception err) {
            throw new IOException("文件下载失败：" + err.getMessage(), err);
        }
    }


}
